/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.jasper.tagplugins.jstl.core;

import org.apache.jasper.compiler.tagplugin.TagPlugin;
import org.apache.jasper.compiler.tagplugin.TagPluginContext;

public class ForTokens implements TagPlugin {

	public void doTag(TagPluginContext ctxt) {
		boolean hasVar, hasVarStatus, hasBegin, hasEnd, hasStep;

		// init the flags
		hasVar = ctxt.isAttributeSpecified("var");
		hasVarStatus = ctxt.isAttributeSpecified("varStatus");
		hasBegin = ctxt.isAttributeSpecified("begin");
		hasEnd = ctxt.isAttributeSpecified("end");
		hasStep = ctxt.isAttributeSpecified("step");

		if (hasVarStatus) {
			ctxt.dontUseTagPlugin();
			return;
		}

		// define all the temp variables' names
		String itemsName = ctxt.getTemporaryVariableName();
		String delimsName = ctxt.getTemporaryVariableName();
		String stName = ctxt.getTemporaryVariableName();
		String beginName = ctxt.getTemporaryVariableName();
		String endName = ctxt.getTemporaryVariableName();
		String stepName = ctxt.getTemporaryVariableName();
		String index = ctxt.getTemporaryVariableName();
		String temp = ctxt.getTemporaryVariableName();
		String tokensCountName = ctxt.getTemporaryVariableName();

		// get the value of the "items" attribute
		ctxt.generateJavaSource("String " + itemsName + " = (String)");
		ctxt.generateAttribute("items");
		ctxt.generateJavaSource(";");

		// get the value of the "delim" attribute
		ctxt.generateJavaSource("String " + delimsName + " = (String)");
		ctxt.generateAttribute("delims");
		ctxt.generateJavaSource(";");

		// new a StringTokenizer Object according to the "items" and the "delim"
		ctxt.generateJavaSource("java.util.StringTokenizer " + stName + " = "
				+ "new java.util.StringTokenizer(" + itemsName + ", "
				+ delimsName + ");");

		// if "begin" specified, move the token to the "begin" place
		// and record the begin index. default begin place is 0.
		ctxt.generateJavaSource("int " + tokensCountName + " = " + stName
				+ ".countTokens();");
		if (hasBegin) {
			ctxt.generateJavaSource("int " + beginName + " = ");
			ctxt.generateAttribute("begin");
			ctxt.generateJavaSource(";");
			ctxt.generateJavaSource("for(int " + index + " = 0; " + index
					+ " < " + beginName + " && " + stName
					+ ".hasMoreTokens(); " + index + "++, " + stName
					+ ".nextToken()){}");
		} else {
			ctxt.generateJavaSource("int " + beginName + " = 0;");
		}

		// when "end" is specified, if the "end" is more than the last index,
		// record the end place as the last index, otherwise, record it as
		// "end";
		// default end place is the last index
		if (hasEnd) {
			ctxt.generateJavaSource("int " + endName + " = 0;");
			ctxt.generateJavaSource("if((" + tokensCountName + " - 1) < ");
			ctxt.generateAttribute("end");
			ctxt.generateJavaSource("){");
			ctxt.generateJavaSource("    " + endName + " = " + tokensCountName
					+ " - 1;");
			ctxt.generateJavaSource("}else{");
			ctxt.generateJavaSource("    " + endName + " = ");
			ctxt.generateAttribute("end");
			ctxt.generateJavaSource(";}");
		} else {
			ctxt.generateJavaSource("int " + endName + " = " + tokensCountName
					+ " - 1;");
		}

		// get the step value from "step" if specified.
		// default step value is 1.
		if (hasStep) {
			ctxt.generateJavaSource("int " + stepName + " = ");
			ctxt.generateAttribute("step");
			ctxt.generateJavaSource(";");
		} else {
			ctxt.generateJavaSource("int " + stepName + " = 1;");
		}

		// the loop
		ctxt.generateJavaSource("for(int " + index + " = " + beginName + "; "
				+ index + " <= " + endName + "; " + index + "++){");
		ctxt.generateJavaSource("    String " + temp + " = " + stName
				+ ".nextToken();");
		ctxt.generateJavaSource("    if(((" + index + " - " + beginName
				+ ") % " + stepName + ") == 0){");
		// if var specified, put the current token into the attribute "var"
		// defines.
		if (hasVar) {
			String strVar = ctxt.getConstantAttribute("var");
			ctxt.generateJavaSource("        pageContext.setAttribute(\""
					+ strVar + "\", " + temp + ");");
		}
		ctxt.generateBody();
		ctxt.generateJavaSource("    }");
		ctxt.generateJavaSource("}");
	}

}
